package com.xbongbong.paas.abstracts;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.help.HttpHelp;
import com.xbongbong.paas.model.PaasFormServiceModel;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.pojo.vo.UserAndDepartmentGetVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.pro.domain.entity.LowCodeServiceInfoEntity;
import com.xbongbong.pro.domain.entity.PaasFormServiceEntity;
import com.xbongbong.pro.enums.businessrule.enums.RuleValueTypeEnum;
import com.xbongbong.pro.enums.lowcode.LowCodeExecuteServiceEnum;
import com.xbongbong.pro.formservice.pojo.ParamValuePojo;
import com.xbongbong.pro.lowcodeexecute.pojo.dto.LowCodeExecuteServiceDTO;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author 吴峰
 * @date 2021/03/18 10:40
 */
@Component
public abstract class AbstractLowCodeExecuteService {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractLowCodeExecuteService.class);

    @Resource
    private HttpHelp httpHelp;
    @Resource
    private PaasFormServiceModel paasFormServiceModel;
    @Resource
    private UserModel userModel;
    @Resource
    private DepartmentModel departmentModel;

    /**
     * 执行服务
     * @param lowCodeExecuteServiceDTO
     * @return
     * @throws XbbException
     */
    public abstract void execute(LowCodeExecuteServiceDTO lowCodeExecuteServiceDTO) throws XbbException;

    /**
     * 发送请求
     * @param lowCodeServiceInfoEntity
     * @param param
     * @throws XbbException
     */
    protected void send(LowCodeServiceInfoEntity lowCodeServiceInfoEntity, JSONObject param) throws XbbException {
        HttpMethod httpMethod = HttpMethod.resolve(lowCodeServiceInfoEntity.getRequestMethod());
        if (Objects.isNull(httpMethod)) {
            return;
        }
        JSONObject header = JSON.parseObject(lowCodeServiceInfoEntity.getRequestHeader());
        String signature = lowCodeServiceInfoEntity.getSignature();

        HttpHelp.setHeader(header, signature, lowCodeServiceInfoEntity.getHmacSecret(), httpMethod, param, lowCodeServiceInfoEntity.getSignatureFlag(), lowCodeServiceInfoEntity.getHmacSecretFlag());
        httpHelp.asyncRequest(header, param, lowCodeServiceInfoEntity.getUrl(), httpMethod);
    }

    /**
     * 获取当前表单的服务
     * @param corpid
     * @param formId
     * @param businessType
     * @param lowCodeExecuteServiceEnum
     * @return
     * @throws XbbException
     */
    protected List<PaasFormServiceEntity> getServiceList(String corpid, Long formId, Integer businessType, LowCodeExecuteServiceEnum lowCodeExecuteServiceEnum) throws XbbException{
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(StringConstant.FORM_ID, formId);
        param.put(StringConstant.BUSINESS_TYPE, businessType);
        switch (lowCodeExecuteServiceEnum) {
            case EDIT:
                param.put("editFlag", 1);
                break;
            case DELETE:
                param.put("deleteFlag", 1);
                break;
            case ADD:
                param.put("commitFlag", 1);
                break;
            default:
                break;
        }
        List<PaasFormServiceEntity> serviceList = paasFormServiceModel.findEntitys(param);
        return serviceList;
    }

    /**
     * 获取服务id列表
     * @param userAndDeptFieldList
     * @param serviceList
     * @param explainMap
     * @param lowCodeExecuteServiceEnum
     * @return
     */
    protected Set<Long> getServiceIdList(Set<String> userAndDeptFieldList, List<PaasFormServiceEntity> serviceList,
                                  Map<String, FieldAttrEntity> explainMap, LowCodeExecuteServiceEnum lowCodeExecuteServiceEnum) {
        Set<Long> serviceIdList = new HashSet<>();
        List<Integer> userAndDeptTypeList = Arrays.asList(FieldTypeEnum.USER.getType(), FieldTypeEnum.USER_GROUP.getType(), FieldTypeEnum.DEPT.getType(), FieldTypeEnum.DEPT_GROUP.getType());
        serviceList.forEach(item->{
            switch (lowCodeExecuteServiceEnum) {
                case EDIT:
                    serviceIdList.add(item.getEditServiceId());
                    break;
                case DELETE:
                    serviceIdList.add(item.getDeleteServiceId());
                    break;
                case ADD:
                    serviceIdList.add(item.getCommitServiceId());
                    break;
                    default:
                    break;
            }
            List<ParamValuePojo> list = JSON.parseArray(item.getDeleteServiceParam(), ParamValuePojo.class);
            list.forEach(paramValuePojo->{
                if (Objects.equals(RuleValueTypeEnum.DYNAMIC_VALUE.getType(), paramValuePojo.getValueType())) {

                    FieldAttrEntity fieldAttrEntity = explainMap.get(paramValuePojo.getValueAttr());
                    if (Objects.nonNull(fieldAttrEntity)) {
                        if (userAndDeptTypeList.contains(fieldAttrEntity.getFieldType())) {
                            userAndDeptFieldList.add(fieldAttrEntity.getAttr());
                        }
                    }
                }
            });
        });
        return serviceIdList;
    }

    /**
     * 获取用户、部门信息
     * @param userAndDeptFieldList
     * @param dataList
     * @param explainMap
     * @param corpid
     * @return
     */
    protected UserAndDepartmentGetVO getUserAndDepartment(Set<String> userAndDeptFieldList, List<PaasFormDataEntityExt> dataList, Map<String, FieldAttrEntity> explainMap, String corpid) {
        UserAndDepartmentGetVO userAndDepartmentGetVO = new UserAndDepartmentGetVO();
        Map<String, UserEntity> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, DepartmentEntity> departmentMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (CollectionsUtil.isNotEmpty(userAndDeptFieldList)) {
            Set<String> userIdList = new HashSet<>();
            Set<Long> departmentIdList = new HashSet<>();
            dataList.forEach(dataEntityExt->{
                JSONObject data = dataEntityExt.getData();
                for (String attr : userAndDeptFieldList) {
                    if (Objects.nonNull(data.get(attr))) {
                        continue;
                    }
                    FieldAttrEntity fieldAttrEntity = explainMap.get(attr);
                    if (Objects.equals(FieldTypeEnum.USER.getType(), fieldAttrEntity.getFieldType())) {
                        userIdList.add(data.getString(attr));
                    } else if (Objects.equals(FieldTypeEnum.USER_GROUP.getType(), fieldAttrEntity.getFieldType())) {
                        userIdList.addAll(JSON.parseArray(JSON.toJSONString(data.get(attr)), String.class));
                    } else if (Objects.equals(FieldTypeEnum.DEPT.getType(), fieldAttrEntity.getFieldType())) {
                        departmentIdList.add(data.getLong(attr));
                    } else if (Objects.equals(FieldTypeEnum.DEPT_GROUP.getType(), fieldAttrEntity.getFieldType())) {
                        departmentIdList.addAll(JSON.parseArray(JSON.toJSONString(data.get(attr)), Long.class));
                    }
                }
            });
            if (CollectionsUtil.isNotEmpty(userIdList)) {
                List<UserEntity> userList = userModel.getByUserIdIn(corpid, new ArrayList<>(userIdList), false);
                userList.forEach(item->{
                    userMap.put(item.getUserId(), item);
                });
            }
            if (CollectionsUtil.isNotEmpty(departmentIdList)) {
                List<DepartmentEntity> departmentList = departmentModel.getByDepIdIn(corpid, departmentIdList);
                departmentList.forEach(item->{
                    departmentMap.put(item.getId().toString(), item);
                });
            }
        }
        userAndDepartmentGetVO.setDepartmentMap(departmentMap);
        userAndDepartmentGetVO.setUserMap(userMap);
        return userAndDepartmentGetVO;
    }
}
